/*
** varfactory.hh
** Login : <David@sandrock.lrde.epita.fr>
** Started on  Tue Apr  8 14:13:34 2003 David Lesage
** $Id: varfactory.hh 34 2003-04-10 22:16:57Z burrus_n $
** 
** Copyright (C) 2003 David Lesage
** This program is free software; you can redistribute it and/or modify
** it under the terms of the GNU General Public License as published by
** the Free Software Foundation; either version 2 of the License, or
** (at your option) any later version.
** 
** This program is distributed in the hope that it will be useful,
** but WITHOUT ANY WARRANTY; without even the implied warranty of
** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
** GNU General Public License for more details.
** 
** You should have received a copy of the GNU General Public License
** along with this program; if not, write to the Free Software
** Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/

#ifndef   	VARFACTORY_HH_
# define   	VARFACTORY_HH_

# include <map>

namespace evz
{
 
  template<class T>
  class Var; // fwd_decl

  template<class T>
  class VarSet; // fwd_decl

  /*--------------.
  | VarFactory<T> |
  `--------------*/

  //! Create and store vars.
  /*!  
    VacFactory creates new Var instances with consistent (unique)
    ranks. Moreover, it stores a map associating all var ranks to the
    Var instances. Internally, variables are represented by their
    rank, so keeping a reference on the VarFactory gives access to the
    Var instances corresponding to the Var ranks.
  */

  template<class T>
  class VarFactory
  {
  private:
    typedef typename std::map<unsigned, Var<T> *> map_type;
    typedef typename map_type::iterator iterator;
    typedef typename map_type::const_iterator const_iterator;
    typedef typename map_type::reverse_iterator reverse_iterator;
    typedef typename map_type::const_reverse_iterator const_reverse_iterator;

  public:
    VarFactory() : rank_(0)
    {}

    // Returns a new allocated Var, with a unique new rank.
    Var<T>& new_var(void)
    {
      Var<T> *v = new Var<T>(rank_);
      vars_[rank_] = v;
      ++rank_;
      return *v;
    }

    // Return the number of variables already allocated. This
    // corresponds the the actual rank, since ranks are allocated
    // continously.
    unsigned size() const
    {
      return rank_;
    }

    // Return the Var instance associated to a Var rank.
    const Var<T>& get_var(unsigned rank) const
    {
      const_iterator it = vars_.find(rank);
      assert(it != vars_.end());
      return *((*it).second);
    }

    // VarFactory are usually unique and passed by reference or
    // pointer between objets. So the comparison requires the same
    // addresses.
    bool operator==(const VarFactory<T>& vf) const
    { 
      return this == &vf;
    }

  private:
    unsigned rank_;
    map_type vars_;
  };

} // end of namespace evz

#endif	    /* !VARFACTORY_HH_ */
